#include <SFML/Graphics/RenderWindow.hpp>
#include <nice2d/macros.h>
#include <nice2d/scene.h>
#include <nice2d/background.h>
#include <nice2d/imagedescriptor.h>
#include <nice2d/util.h>
#include <nice2d/tilemap.h>
#include <nice2d/widgets/desktop.h>
#include <nice2d/components/group.h>
#include <nice2d/components/spritestatus.h>
#include <nice2d/components/imagemanager.h>
#include <nice2d/components/attributetable.h>
#include <nice2d/piece/movepointsearcher.h>
#include <nice2d/piece/piecescene.h>
#include <nice2d/piece/factionmanager.h>

#define SCENE_WIDTH  900.0f
#define SCENE_HEIGHT 680.0f

class UnitScene : public PieceScene
{
public:
    void onInitialed()override
    {
        auto factionManager = GET_APPLICATION_COMPONENT(FactionManager);
        factionManager->createFaction(sf::Color::Red, L"red");
        factionManager->createFaction(sf::Color::Green, L"green");

        setSceneBox({0.0f, 0.0f, SCENE_WIDTH, SCENE_HEIGHT});
        setBackground(Background::create("./../data/images/ground3.png", true));

        tileMap = TileMap::create(TileMapType::TileMapType_Hex);
        tileMap->init(13, 9, 96);
        tileMap->setTextVisible(true);

        tileMap->accept([](int32_t x, int32_t y, std::shared_ptr<Tile> tile) {
            tile->setOutlineColor(sf::Color(128, 128, 128));
            tile->setOutlineThickness(0.5f);

            tile->setWalkable(true);
        });

        addChild(tileMap);
        setTileMap(tileMap);
        tileMap->tileClicked.connect(std::bind(&UnitScene::tileClicked, this, std::placeholders::_1,
                                               std::placeholders::_2));

        searcher = ADD_COMPONENT(Application::getInstance(), MovePointSearcher);
        searcher->setOwner(tileMap);

        attributeTable = ADD_COMPONENT(Application::getInstance(), AttributeTable2D);
        attributeTable->add(0, 1, 4);

        auto attributeTable3d = ADD_COMPONENT(Application::getInstance(), AttributeTable3D);
        attributeTable3d->add(0, 0, AttributeTable_Move, 1);

        TextOption opt;
        opt.characterSize = 15;

        sf::Color spriteColor[] = {sf::Color::Red, sf::Color::Green};

        for (int i = 0; i < 24; i++) {
            auto piece = std::make_shared<Piece>(opt);
            piece->setName(std::wstring(L"Piece:") + std::to_wstring(i + 1));
            piece->setHitPoint(rand() % 5 + 1);
            piece->setAttack(rand() % 5 + 1);
            piece->setDefense(rand() % 5 + 1);
            piece->setMovement(rand() % 5 + 1);
            piece->setBackgroundColor(sf::Color(140, 140, 140));
            piece->setSpriteColor(spriteColor[rand() % 2]);
            piece->setSize(64, 64);
            piece->addPieceIcon("./../data/icon/nato/units/infantry.png");
            piece->addPieceIcon("./../data/icon/nato/sizes/group.png");
            piece->setTextColor(sf::Color::White);
            addPiece(piece, rand() % 13, rand() % 9);

            piece->selected.connect(std::bind(&UnitScene::spriteSelected, this, std::placeholders::_1));
        }
    }

    void tileClicked(int32_t x, int32_t y)
    {
        auto tile = tileMap->getTileByIndex(x, y);
        if (!tile)
            return;

        auto sprite = tile->getSprite();
        if (sprite) {
            tileMap->accept([](int32_t x, int32_t y, std::shared_ptr<Tile> tile) {
                tile->setFillColor(sf::Color::Transparent);
            });

            sprite->select();

            auto tileColor = sprite->getSpriteColor();
            tileColor.a = 36;

            auto list = searcher->search(tileMap, {x, y}, sprite->getSpriteColor(), 0);
            auto itr = list.begin();
            while (itr != list.end()) {
                auto tile = tileMap->getTileByIndex(itr->x, itr->y);
                tile->setFillColor(tileColor);
                itr ++;
            }
        }
    }

    void spriteSelected(SpritePointer sprite)
    {
        auto visitor = std::make_shared<PieceVisitor>();
        acceptPieces(visitor);

        sprite->setBackgroundColor(sf::Color(180, 180, 180));

        auto pieces = visitor->getPieces();
        std::for_each(pieces.begin(), pieces.end(), [&](std::shared_ptr<Piece> piece) {
            if (std::dynamic_pointer_cast<Piece>(sprite) != piece) {
                piece->unselect();
                piece->setBackgroundColor(sf::Color(140, 140, 140));
            }
        });
    }
private:
    std::shared_ptr<TileMap> tileMap;
    std::shared_ptr<AttributeTable2D> attributeTable;
    std::shared_ptr<MovePointSearcher> searcher;
};

DECLARE_MAIN_FUNCTION_WITH_SCENE(SCENE_WIDTH, SCENE_HEIGHT, "unit17", UnitScene)
